作者:李旺成
时间:2016年5月6日
在这个 Hack 中将详细介绍
标签的使用,以及一些注意事项。
一、每个页面添加页脚
假设:现在有这样一个需求,为应用中的每个页面都添加一个页脚。这里简单处理,要添加的页脚就是一个显示应用名称的文本(使用 TextView 来显示),如上图所示。大多数的应用都是由多个 Activity 组成的,多个 Activity 一般对应多个布局文件。那是不是要把这个页脚 TextView 一个个拷贝到每个布局文件中?
听过这么一句话:当你的程序中出现大量的重复代码时你得小心了。(不是我杜撰的,大致是这个意思,没有找到出处…)
确实是这样,不要把一段相同的代码到处“复制/粘贴”,有一个很明显的弊端摆在眼前,如果以后需要修改这段代码就悲剧了。
所以,要实现上述需求“复制/粘贴”不是我们要的解决方案。解决该问题最简单的方法是使用
好了需求明确的,看看怎么实现。
使用 标签为页面添加页脚
首先,创建一个页脚布局 footer_app_name.xml:1
2
3
4
5
6
7
8
9<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:text="AndroidHacksLayout"
android:textColor="@android:color/holo_red_dark"/>
然后,使用 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.diygreen.androidhackslayout.Hack2Activity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="演示使用 <include /> 标签避免代码重复"/>
<!-- 插入页脚 -->
<include
layout="@layout/footer_app_name"/>
</RelativeLayout>
上面的示例代码很简单,为
上图中可以看到,将根布局修改为 FrameLayout 之后,“页脚”就不是在该页面的底部了,那要怎么做了?不急,下面会给出解决方案,且继续往下阅读。
二、 标签使用详解
include 属性有两种设置方式
1、在子布局中设置
就是上面的示例代码中使用的方式,直接在子布局中设置好所有的属性,使用的时候只需要在主布局中为 include 设置 layout 属性即可。
这样用很方便,但是 Android 中提供了很多布局技术,你在子布局中设置的属性可能只适用与某一个/某一类布局。上面的示例中就是这样,只有主布局为 RelativeLayout 的时候页面才能在指定位置显示,如果替换为 FrameLayout 就显示不正确了。这就反映了一个问题 —— 不灵活。那怎么解决呢?include 属性还有另外一种设置方式。
2、在
说到这里,那先把示例中遗留的问题解决了,就是将 RelativeLayout 替换为 FrameLayout 之后页面位置的问题。
先看解决后的效果:
解决方案代码:1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
>
...
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
layout="@layout/footer_app_name"/>
</FrameLayout>
上面的示例代码中与根布局为 RelativeLayout 对比的主要修改处是在
说明:其实和 style 的使用非常类似,你可以直接使用 style,也可以覆盖 style 中的一些属性。
在
- 创建页面 header_app_name.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="我是-页眉-"
android:textColor="@android:color/holo_blue_dark"/>
```
2. 使用 <include /> 标签添加页眉
```java
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
layout="@layout/header_app_name"/>
效果如下:
注意:在示例中页面布局的宽度高度都设置为 0dp 了,这么做的目的就是由 header_app_name.xml 文件的使用者在
三、 标签注意事项
这里罗列了一些我在使用
findViewById 出现 NullPointerException
具体情况是这样的,如果 include 一个布局时,并没有给
但是,一旦你为
标签失效了
Android 的缺陷(Issue)跟踪系统中报告过一个缺陷,缺陷的标题是:“
这个 issue 描述的问题在一定程度上是正确的,问题出在如果想在
PS:话说如果你是用 AndroidStudio 的话,可能根本就不会遇到这个问题,因为,如果你在指定其他的 android:layout_* 属性时,如果没有同时指定 android:layout_width 和 android:layout_height 这两个属性,AndroidStudio 是会报错的:
自定义控件与
如果是一些比较简单,include 进来之后不需要有过多操作的,使用
项目地址
AndroidHacks合集
布局篇
个人博客
示例用到代码见:
Hack2Activity.java
activity_hack2_1.xml
activity_hack2_2.xml
header_app_name.xml
footer_app_name.xml